from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QImage, QCursor
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsPixmapItem
from PyQt5 import QtGui,QtCore,uic
from PyQt5 import QtWidgets
from PyQt5.Qt import QPixmap, QPoint, Qt, QPainter, QIcon
import matplotlib.pyplot as plt
import cv2
import skimage
import numpy as np

def resource_path(relative_path):
    import sys, os
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.abspath(relative_path)

class Merge_Window(QWidget):
    signal = pyqtSignal(object, object, object, object)
    def __init__(self, our_img,graph,scene,name):
        super().__init__()
        self.ourimg = our_img
        self.graph = graph
        self.name = name
        self.scene_view = scene
        self.a = 0
        self.b = 0
        self.c = 0
        self.item = None
        self.initial_scale = 0.31/2/6.25/(800/self.ourimg.height) if self.ourimg.height > 5000 else 1
        self.init_set()
        self.init_ui()
        

    def init_set(self):
        pixmap = array_to_pixmap(self.ourimg.img,self.a,self.b,self.c)
        self.item = MyGraphicsPixmapItem(pixmap, self.signal, initial_scale=self.initial_scale)
        self.item.setPos(430 - pixmap.size().width() // 2, 430 - pixmap.size().height() // 2)
        self.center_pos = QPoint(430 - pixmap.size().width() // 2, 430 - pixmap.size().height() // 2)
        self.scene_view.addItem(self.item)
        self.item.update()
        self.update()

    def init_ui(self):
        self.ui = uic.loadUi(resource_path("img_merge_adjust.ui"))
        self.ui.activateWindow()
        self.ui.setWindowTitle(self.name)
        self.ui.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        #lineEdit组件
        self.angle_set = self.ui.lineEdit
        self.scale_set = self.ui.lineEdit_2
        self.speed_set = self.ui.lineEdit_5
        self.opacity_set = self.ui.lineEdit_6
        self.opacity_set.setText('%.4f'%(1.00))
        self.movePos_x = self.ui.lineEdit_3
        self.movePos_y = self.ui.lineEdit_4
        self.binary_a = self.ui.lineEdit_8
        self.binary_b = self.ui.lineEdit_7
        self.binary_c = self.ui.lineEdit_9
        self.freeze_button = self.ui.radioButton

        self.speed_set.editingFinished.connect(self.adjust_speed)
        self.opacity_set.editingFinished.connect(self.adjust_opacity)
        self.freeze_button.clicked.connect(self.adjust_freeze)
        self.movePos_x.editingFinished.connect(self.adjust_pos_x)
        self.movePos_y.editingFinished.connect(self.adjust_pos_y)
        self.binary_a.textChanged.connect(self.adjust_binary)
        self.binary_b.textChanged.connect(self.adjust_binary)
        self.binary_c.textChanged.connect(self.adjust_binary)
        #self.angle_set.editingFinished.connect(self.adjust_angle)
        #self.scale_set.editingFinished.connect(self.adjust_scale)

        self.signal.connect(self.show_pannel)

        self.graph.setScene(self.scene_view)
        self.ui.closeEvent = self.closeEvent

    def show_pannel(self, rotate_angle,scale_size,moveSpeed,pos):
        # 计算移动的x坐标
        self.move_x = -self.center_pos.x() + pos().x()
        # 计算移动的y坐标
        self.move_y = self.center_pos.y() - pos().y()
        # 设置旋转角度
        self.angle_set.setText('%.4f'%(rotate_angle))
        # 设置缩放大小
        self.scale_set.setText('%.4f'%(scale_size))
        # 设置移动速度
        self.speed_set.setText('%.4f'%(moveSpeed))
        # 设置移动的x坐标
        self.movePos_x.setText("%d" % (self.move_x))
        # 设置移动的y坐标
        self.movePos_y.setText("%d" % (self.move_y))
        # 保存图像
        self.save_image()

    def adjust_speed(self):
        text = self.speed_set.text()
        print('text')
        text = float(text)
        self.item.moveSpeed = text

    def adjust_opacity(self):
        text = self.opacity_set.text()
        text = float(text)
        self.item.setOpacity(text)

    def adjust_pos_x(self):
        x = int(self.movePos_x.text())
        self.item.setPos(x+self.center_pos.x(),self.item.pos().y())

    def adjust_pos_y(self):
        y = int(self.movePos_y.text())
        self.item.setPos(self.item.pos().x(), self.center_pos.y() - y)

    def adjust_binary(self):
        self.a = int(self.binary_a.text())
        self.b = int(self.binary_b.text())
        self.c = int(self.binary_c.text())
        self.scene_view.removeItem(self.item)
        self.init_set()
        self.save_image()

    def adjust_freeze(self):
        self.item.freezed = self.freeze_button.isChecked()
        self.item.freeze()

    def save_image(self):
        self.ourimg.angle = self.item.rotate_angle
        self.ourimg.move_x = self.move_x
        self.ourimg.move_y = self.move_y
        self.ourimg.scale_all = float(self.ourimg.scale)*float(self.item.scale_size)
        self.ourimg.a = self.a
        self.ourimg.b = self.b
        self.ourimg.c = self.c
        #image = QImage(self.item.scene().sceneRect().size().toSize(), QImage.Format_ARGB32)
        #painter = QPainter(image)
        #self.item.scene().render(painter)
        #painter.end()
        #fname, _ = QFileDialog.getSaveFileName(self, 'Open file he', '..')
        #image.save(fname)

    def closeEvent(self,event):
        self.scene_view.removeItem(self.item)
        print(self.scene_view.items())


class MyGraphicsPixmapItem(QGraphicsPixmapItem):
    def __init__(self,pixmap,signal,initial_scale):
        super().__init__()
        self.pixmap = pixmap
        self.setPixmap(self.pixmap)
        self.chosed = True
        self.wheelmove = 0
        self.wheelmove0 = initial_scale
        self.rotate_angle = 0
        self.scale_size = initial_scale
        self.moveSpeed = 0.01
        self.signal = signal
        self.freezed = False
        self.freeze()
        self.our_cursor = rotate_index()
        self.setCursor(self.our_cursor)
        self.setScale(initial_scale)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
        center_point = QPoint(self.pixmap.size().width()//2,self.pixmap.size().height()//2)
        self.setTransformOriginPoint(center_point)
    
    def paint(self,painter,option,widget=None):
        super().paint(painter,option,widget)

        self.signal.emit(self.rotate_angle,self.scale_size,self.moveSpeed,self.pos)

        if self.chosed:
            painter.drawPixmap(0,0, self.pixmap)
        else:
            painter.drawPixmap(0,0,self.pixmap)
            #self.setFlag()
        
    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionHasChanged:
            self.signal.emit(self.rotate_angle, self.scale_size, self.moveSpeed, self.pos)
        return super().itemChange(change, value)

    def mouseDoubleClickEvent_work(self, event):
        if event.button() == Qt.LeftButton:
            if self.chosed:
                self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, False)
                self.setCursor(self.our_cursor)
            else:
                self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True)
                self.setCursor(Qt.SizeAllCursor)
            self.chosed = not self.chosed
            self.update()

    def wheelEvent_work(self,event):
        angle = event.delta()/120
        center_point = QPoint(self.pixmap.size().width()//2,self.pixmap.size().height()//2)
        self.setTransformOriginPoint(center_point)

        if not self.chosed:
            if angle > 0:
                self.wheelmove = self.wheelmove + self.moveSpeed
            if angle < 0:
                self.wheelmove = self.wheelmove - self.moveSpeed
            self.rotate_angle = (self.wheelmove % 1) * 360.0
            self.setRotation(self.rotate_angle)

        else:
            if angle > 0:
                self.wheelmove0 = self.wheelmove0 + self.moveSpeed
                if self.wheelmove0 <= 3:
                    self.scale_size = self.wheelmove0
                else:
                    self.wheelmove0 = 3
                    self.scale_size = 3

            if angle < 0:
                self.wheelmove0 = self.wheelmove0 - self.moveSpeed
                if self.wheelmove0 >= 0.2:
                    self.scale_size = self.wheelmove0
                else:
                    self.wheelmove0 = 0.2
                    self.scale_size = 0.2
            self.setScale(self.scale_size)
        self.update()

    def mouseDoubleClickEvent_ori(self,event):
        self.chosed = False
        self.setCursor(Qt.SizeAllCursor)

    def wheelEvent_ori(self,event):
        self.chosed = False
        self.setCursor(Qt.SizeAllCursor)

    def freeze(self):
        if self.freezed:
            self.wheelEvent = self.mouseDoubleClickEvent_ori
            self.mouseDoubleClickEvent = self.wheelEvent_ori
            self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, False)
            self.setCursor(Qt.SizeAllCursor)

        else:
            self.wheelEvent = self.wheelEvent_work
            self.mouseDoubleClickEvent =self.mouseDoubleClickEvent_work
            self.chosed = False
            self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True)
            self.setCursor(Qt.SizeAllCursor)

def rotate_index():
    img = skimage.io.imread(resource_path('rotate_consor.jpg'))
    x = np.expand_dims(img[:, :, 0], 2)
    y = np.expand_dims(img[:, :, 1], 2)
    z = np.expand_dims(img[:, :, 2], 2)
    aa = np.ones_like(x, dtype=np.uint8) * 255
    mask_0 = (x >= 240 ) & (y >= 240) & (z >= 240)
    aa[mask_0] = 0
    img = np.concatenate([x, y, z, aa], axis=2)
    img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
    height, width, channel = img.shape
    bytesPerLine = 4 * width
    img = QtGui.QImage(img, width, height, bytesPerLine, QtGui.QImage.Format_RGBA8888)
    pixmap = QtGui.QPixmap.fromImage(img)
    pixmap = pixmap.scaled(30, 30)
    cursor = QCursor(pixmap,0,0)
    return cursor

def array_to_pixmap(img,a,b,c):
    img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
    if len(img.shape) <= 2:
        img = plt.cm.magma(img)
        img = skimage.color.rgba2rgb(img)
        img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)

    img = set_binary(img,a,b,c)
    height,width,channel = img.shape
    bytesPerLine = 4*width
    img = QtGui.QImage(img, width, height, bytesPerLine, QtGui.QImage.Format_RGBA8888)
    return QtGui.QPixmap.fromImage(img)

def pixmap_to_array(pixmap):
    w,h = pixmap.size().width(),pixmap.size().height()
    img = pixmap.toImage()
    byte_str = img.bits().asstring(w*h*4)
    img = np.frombuffer(byte_str,dtype=np.uint8).reshape((h,w,4))
    img = skimage.color.rgba2rgb(img)
    img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
    return img

def set_binary(img,a,b,c):
    img = img.copy()
    x = np.expand_dims(img[:, :, 0], 2)
    y= np.expand_dims(img[:, :, 1], 2)
    z = np.expand_dims(img[:, :, 2], 2)
    aa = np.ones_like(x, dtype=np.uint8) * 255
    mask_0 = (x <= a) & (y <= b) & (z <= c)
    aa[mask_0] = 0
    img = np.concatenate([x,y,z,aa],axis=2)
    return img
